package cn.geminis.warehouse.service.inventory.service;

import cn.geminis.warehouse.service.basic.entity.ProductBatch;
import cn.geminis.warehouse.service.inventory.entity.Container;
import cn.geminis.warehouse.service.inventory.entity.ContainerInContainer;
import cn.geminis.warehouse.service.inventory.entity.ProductBatchInContainer;
import cn.geminis.warehouse.service.inventory.entity.filter.ContainerInContainerFilter;
import cn.geminis.warehouse.service.inventory.entity.filter.ProductBatchInContainerFilter;
import cn.geminis.warehouse.service.inventory.entity.repository.ContainerInContainerRepository;
import cn.geminis.warehouse.service.inventory.entity.repository.ContainerRepository;
import cn.geminis.warehouse.service.inventory.entity.repository.ProductBatchInContainerRepository;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.stream.Collectors;

@Service
@RequiredArgsConstructor
public class InventoryService {

    private final ContainerInContainerRepository containerInRepository;
    private final ContainerRepository containerRepository;
    private final ProductBatchInContainerRepository productBatchInContainerRepository;

    @Transactional(rollbackFor = Exception.class)
    public void packageContainer(Container parent, Container child) {
        if (child.isContained()) {
            throw new RuntimeException("该容器已在其他容器内");
        }
        child.setContained(true);
        this.containerRepository.save(child);

        var records = this.containerInRepository
                .findAll(
                        ContainerInContainerFilter.builder()
                                .childId(parent.getId())
                                .build()
                )
                .stream().map(ContainerInContainer::getParent)
                .collect(Collectors.toList());
        records.add(parent);
        records.forEach(data -> {
            var record = new ContainerInContainer();
            record.setParent(data);
            record.setChild(child);
            this.containerInRepository.save(record);
        });
    }

    @Transactional(rollbackFor = Exception.class)
    public void unPackageContainer(Container parent, Container child) {
        if (!child.isContained()) {
            throw new RuntimeException("该容器未在其他容器内");
        }
        child.setContained(false);
        this.containerInRepository.unPackageAllByChildId(child.getId());
    }

    public void containerProductBatchChange(ProductBatch productBatch, Container container, int amount) {
        if (amount == 0) {
            return;
        }
        this.productBatchInContainerRepository
                .findOne(
                        ProductBatchInContainerFilter.builder()
                                .containerId(container.getId())
                                .productBatchId(productBatch.getId())
                                .build()
                )
                .ifPresentOrElse((data) -> {
                            var newAmount = data.getAmount() + amount;
                            if (newAmount < 0) {
                                throw new RuntimeException("库存不足");
                            }
                            if (newAmount == 0) {
                                this.productBatchInContainerRepository.delete(data);
                            } else {
                                data.setAmount(newAmount);
                                this.productBatchInContainerRepository.save(data);
                            }
                        },
                        () -> {
                            if (amount < 0) {
                                throw new RuntimeException("库存不足");
                            }
                            var data = new ProductBatchInContainer();
                            data.setProductBatch(productBatch);
                            data.setContainer(container);
                            data.setAmount(amount);
                            this.productBatchInContainerRepository.save(data);
                        });
    }

}
